package top.heue.utils.base.helper

import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.content.UriPermission
import android.net.Uri
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContract
import top.heue.utils.base.util.file.SAFUtil
import top.heue.utils.log.L


/**
 * SAF相关操作辅助类
 *
 * I,O详细参考ActivityResultContracts
 */
class SAFHelper<I, O>(private val context: Context) {
    private var launcher: ActivityResultLauncher<I>? = null
    private var onResult: (SAFHelper<I, O>.(out: O?) -> Unit)? = null
    private val packageName: String = context.packageName
    val safUtil: SAFUtil by lazy { SAFUtil(context) }
    private var activity: ComponentActivity? = null

    constructor(activity: ComponentActivity) : this(activity as Context) {
        this.activity = activity
    }

    companion object {
        private const val TAKE_FLAGS =
            Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION

        fun <I, O> with(activity: ComponentActivity) = SAFHelper<I, O>(activity)

        /**
         * 列出所有授权过的Uri
         */
        fun grantedUri(contentResolver: ContentResolver): MutableList<UriPermission> =
            contentResolver.persistedUriPermissions
    }

    /**
     * 设置访问的目标
     */
    fun target(contract: ActivityResultContract<I, O>) = apply {
        if (activity == null) {
            L.w("该saf不是以activity构建，无法请求文件和持有文件权限")
            return@apply
        }
        launcher = activity!!.registerForActivityResult(contract) {
            onResult?.invoke(this, it)
        }
    }

    /**
     * 事件结果回调
     */
    fun onResult(onResult: ((SAFHelper<I, O>.(out: O?) -> Unit))) = apply {
        this.onResult = onResult
    }

    /**
     * 持有该Uri
     */
    private fun takeUriPermission(activity: ComponentActivity, treeUri: Uri) {
        activity.contentResolver.takePersistableUriPermission(treeUri, TAKE_FLAGS)
    }

    /**
     * 持有该Uri
     */
    fun takeUri(uri: Uri) {
        //持久化当前Uri权限
        context.grantUriPermission(packageName, uri, TAKE_FLAGS)
        if (activity == null) {
            L.w("该saf不是以activity构建，无法请求文件和持有文件权限")
            return
        }
        takeUriPermission(activity!!, uri)
    }

    /**
     * 释放以前授权过的Uri
     */
    fun releaseAllGrantedUri() {
        //释放之前的所有文件权限
        val pup = grantedUri
        for (up in pup) {
            releaseGrantedUri(up.uri)
        }
    }

    /**
     * 释放以前授权过的Uri
     */
    fun releaseGrantedUri(uri: Uri) {
        //释放指定文件权限
        context.revokeUriPermission(uri, TAKE_FLAGS)
    }

    /**
     * 开始请求操作
     */
    fun get(input: I? = null) = run {
        if (activity == null)
            throw UninitializedPropertyAccessException("该saf不是以activity构建，无法请求文件和持有文件权限")
        if (launcher == null) throw UninitializedPropertyAccessException("未调用target()设置启动目的")
        launcher!!.launch(input)
    }

    /**
     * 列出当前activity所有授权过的Uri
     */
    val grantedUri: MutableList<UriPermission> get() = context.contentResolver.persistedUriPermissions
}